/*
 * @(#)LoginAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.web;

import java.sql.Connection;
import java.util.List;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.AuditLoginOut;
import com.dcivision.user.auth.AuthenticationHandler;
import com.dcivision.user.bean.UserRecord;
import com.dcivision.user.dao.UserRecordDAObject;

/**
 LoginAction.java
 
 This class is an action for login.
 
 @author          Beyond Qu
 @company         DCIVision Limited
 @creation date   11/08/2004
 @version         $Revision: 1.6.2.2 $
 */

public class ODMALoginAction extends LoginAction {
  
  private String processFlag = "";      
  
  public ODMALoginAction() {
    super();
    
  }
  
  
  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException {
    try {
      this.authHandler = (AuthenticationHandler)Class.forName(SystemParameterFactory.getSystemParameter(SystemParameterConstant.AUTHENICATION_CLASS)).newInstance();
    } catch (Exception e) {
      log.error("Authenication Handler class not found.", e);
      throw new ApplicationException(ErrorConstant.LOGIN_AUTH_CLASS_NOT_FOUND);
    }
    
    LoginForm loginForm = (LoginForm)form;
    SessionContainer sessionCtn = this.getSessionContainer(request);
    UserRecord userRecord = null;
    Connection conn = null;
    
    //if this is odma process    
    processFlag = request.getParameter("odmaProcess");
    if(Utility.isEmpty( processFlag)) {
      processFlag = request.getParameter("processFlag");
    }
    
    String updateAlertSystemLogID = request.getParameter("updateAlertSystemLogID");
    
    String loginPwd  = loginForm.getLoginPwd();
    String auditStatus = "";
    String userIP = request.getRemoteAddr();
    
    try {
      // Check whether it is a demo version.
      if (sessionCtn != null && sessionCtn.getAppContainer() != null && sessionCtn.getAppContainer().isDemoVersion() && sessionCtn.getAppContainer().getCurrentLoginUserList().size() >= 2) {
        log.info("This is a demo version of ParaDM. Only 2 concurrent users are allowed.");
        throw new ApplicationException(ErrorConstant.LOGIN_DEMO_TOO_MANY_CONCURRENT_USER);
      }
      
      // Check whether session is expired.
      if ("expire".equals(loginForm.getAction())) {
        log.debug("Session is expired");
        this.authHandler.Logout(sessionCtn, request);
        throw new ApplicationException(ErrorConstant.LOGIN_SESSION_EXPIRED);
      }
      
      if (!"login".equals(loginForm.getAction())) {
        if ("redirect".equals(loginForm.getAction())) {
          String userID = request.getParameter("userID");
          if (sessionCtn == null || Utility.isEmpty(sessionCtn.getUserRecordID()) || (!Utility.isEmpty(userID) && !sessionCtn.getUserRecordID().equals(TextUtility.parseIntegerObj(userID))) ) {
            this.addError(request, "common.message.login_redirect");
            return mapping.findForward("LOGIN");
          } else {
            // Redirect the page to the previous access page.
            if (!Utility.isEmpty(loginForm.getUrl())) {
              try {
                String redirectURL = loginForm.getUrl();
                if (redirectURL.indexOf("isLogin=") < 0) {
                  if (redirectURL.indexOf("?") > 0) {
                    redirectURL += "&isLogin=Y";
                  } else {
                    redirectURL += "?isLogin=Y";
                  }
                }
                response.sendRedirect(redirectURL);
              } catch (Exception ignore) {
                log.error("Cannot redirect url.", ignore);
              }
            } else {
              return mapping.findForward("LOGIN");
            }
          }
        }
        return mapping.findForward("LOGIN");
      }
      
      Locale prevLocale = (Locale)request.getSession().getAttribute(org.apache.struts.Globals.LOCALE_KEY);
      if (prevLocale!=null) {
        request.getSession().setAttribute(org.apache.struts.Globals.LOCALE_KEY, prevLocale);
      }
      conn = getConnection(request);
      
      // Special handling to avoid un-logout session variable remains in the same session.
      SessionContainer tmpSessionCtn = new SessionContainer();
      userRecord = this.authHandler.Login(loginForm, tmpSessionCtn, request, conn);
      //request.getSession().setAttribute(GlobalConstant.SESSION_CONTAINER_KEY, tmpSessionCtn);
      sessionCtn = (SessionContainer)request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
      
      AuditLoginOut audit = auditLogin(conn, request, userRecord.getID(), userIP, AuditLoginOut.STATUS_LOGIN_SUCCESS, request.getSession().getId(), userRecord.getLoginName());
      
      sessionCtn.setUserRecord(userRecord);
      sessionCtn.setLoginTime(audit.getLoginDatetime());
      sessionCtn.setUserIPAddress(userIP);
      if (!Utility.isEmpty(userRecord.getLocale())) {
        sessionCtn.setLocale(Utility.getLocaleByString(userRecord.getLocale()));
      } else if (prevLocale!=null) {
        sessionCtn.setLocale(prevLocale);
      }
      
      if (AuditLoginOut.STATUS_PASSWORD_EXPIRED.equals(sessionCtn.getLoginStatus())) {
        request.setAttribute("ID", userRecord.getID());
        return mapping.findForward("CHG_PWD");
      }
      sessionCtn.setLoginStatus(AuditLoginOut.STATUS_LOGIN_SUCCESS);
      
      //reset  the clipboard items for each login
      if (!Utility.isEmpty(request.getSession().getAttribute("DMS_CLIPBOARD"))){
        List clipBoardList = (List)request.getSession().getAttribute("DMS_CLIPBOARD");
        clipBoardList.removeAll(clipBoardList);
        request.getSession().setAttribute("DMS_CLIPBOARD", clipBoardList);
      }
      
      
      // Store the client screen resolution in session variable.
      request.getSession().setAttribute(GlobalConstant.CLIENT_SCREEN_WIDTH_KEY, loginForm.getClientScreenWidth());
    } catch (ApplicationException appEx) {
      if (!"odma".equals(processFlag)){        
        addError(request, appEx.getActionError());
      }
      if((ErrorConstant.LOGIN_WRONG_PASSWORD).equals(appEx.getMsgCode())) {
        auditStatus = AuditLoginOut.STATUS_WRONG_PASSWORD;
        UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
        userRecord = (UserRecord)userRecordDAO.getObjectByLoginName(loginForm.getLoginName());
        auditLogin(conn, request, userRecord.getID(), userIP, auditStatus,request.getSession().getId(), userRecord.getLoginName());
        if ("odma".equals(processFlag)){            
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_01" );      
          request.setAttribute("message","Invalid password");
          //return mapping.findForward("HOME");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{
          return mapping.findForward("LOGIN");
        }  
      } else if((ErrorConstant.LOGIN_ACCOUNT_LOCKED).equals(appEx.getMsgCode())) {
        if ("odma".equals(processFlag)){
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_02" );
          request.setAttribute("message","User account is locked");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{
          auditStatus = AuditLoginOut.STATUS_ACCOUNT_LOCKED;
          UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
          userRecord = (UserRecord)userRecordDAO.getObjectByLoginName(loginForm.getLoginName());
          auditLogin(conn, request, userRecord.getID(), userIP, auditStatus,request.getSession().getId(), userRecord.getLoginName());
          return mapping.findForward("LOGIN");
        }
      } else if((ErrorConstant.LOGIN_ACCOUNT_LOCKED_ATTEMPT).equals(appEx.getMsgCode())) {
        if ("odma".equals(processFlag)){
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_03" );
          request.setAttribute("message","User account is locked, login attempt failure");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{        
          auditStatus = AuditLoginOut.STATUS_ATTEMPT_EXCESS;
          UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
          userRecord = (UserRecord)userRecordDAO.getObjectByLoginName(loginForm.getLoginName());
          auditLogin(conn, request, userRecord.getID(), userIP, auditStatus,request.getSession().getId(), userRecord.getLoginName());
          return mapping.findForward("LOGIN");
        }
      } else if((ErrorConstant.LOGIN_DOUBLE_LOGIN).equals(appEx.getMsgCode())) {
        if ("odma".equals(processFlag)){
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_04" );
          request.setAttribute("message","Double login detected");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{        
          auditStatus = AuditLoginOut.STATUS_DUPLICATE_LOGIN;
          UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
          userRecord = (UserRecord)userRecordDAO.getObjectByLoginName(loginForm.getLoginName());
          auditLogin(conn, request, userRecord.getID(), userIP, auditStatus,request.getSession().getId(), userRecord.getLoginName());
          return mapping.findForward("LOGIN");
        }
      } else if((ErrorConstant.LOGIN_PASSWORD_EXPIRED).equals(appEx.getMsgCode())) {
        if ("odma".equals(processFlag)){
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_05" );
          request.setAttribute("message","Password expired");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{        
          auditStatus = AuditLoginOut.STATUS_PASSWORD_EXPIRED;
          UserRecordDAObject userRecordDAO = new UserRecordDAObject(sessionCtn, conn);
          userRecord = (UserRecord)userRecordDAO.getObjectByLoginName(loginForm.getLoginName());
          auditLogin(conn, request, userRecord.getID(), userIP, auditStatus,request.getSession().getId(), userRecord.getLoginName());
          return mapping.findForward("CHG_PWD");
        }
      } else if((ErrorConstant.LOGIN_SESSION_EXPIRED).equals(appEx.getMsgCode())) {
        if ("odma".equals(processFlag)){
          request.setAttribute("odmaGetType","login" );
          request.setAttribute("result","failed" );
          request.setAttribute("inforCode","ERROR_LOGIN_06" );
          request.setAttribute("message","Session expired");
          return mapping.findForward("DMS.ODMA_RESULT");
        }else{
          return mapping.findForward("LOGIN");
        }        
      }
      if ("odma".equals(processFlag)){
        request.setAttribute("odmaGetType","login" );
        request.setAttribute("result","failed" );
        request.setAttribute("inforCode","ERROR_LOGIN_07" );
        request.setAttribute("message","This user isn't exist");
        return mapping.findForward("DMS.ODMA_RESULT");
      }if ("alertMessage".equals(processFlag)){
        request.setAttribute("odmaGetType","login" );
        request.setAttribute("result","failed" );
        request.setAttribute("inforCode","ERROR_LOGIN_07" );
        return mapping.findForward("DMS.ODMA_RESULT");            
      }else{    
        return mapping.findForward("LOGIN");
      }  
    }
    
    // Redirect the page to the previous access page.
    if (!Utility.isEmpty(loginForm.getUrl())) {
      try {
        String userID = request.getParameter("userID");
        if (!Utility.isEmpty(userID) && !sessionCtn.getUserRecordID().equals(TextUtility.parseIntegerObj(userID))) {
          //login user is not the target user, redirect to HOME page
          // for odma return
          if ("odma".equals(processFlag)){         
            if ((sessionCtn.hasAccessRight(SystemFunctionConstant.DMS_PUBLIC_FOLDER, "R"))
                || (sessionCtn.hasAccessRight(SystemFunctionConstant.DMS_PERSONAL_FOLDER, "R"))){
              request.setAttribute("odmaGetType","login" );
              request.setAttribute("result","success" );
              request.setAttribute("inforCode","MESSAGE_LOGIN_01" );
              request.setAttribute("message","Login Successfully");
              return mapping.findForward("DMS.ODMA_RESULT");        
            }else{// if not right access dms, don't allow user login                 
              request.setAttribute("odmaGetType","login" );
              request.setAttribute("result","failed" );
              request.setAttribute("inforCode","ERROR_LOGIN_08" );
              request.setAttribute("message","Not right access dms, don't allow user login");
              return mapping.findForward("DMS.ODMA_RESULT");
            }
          }else if ("alertMessage".equals(processFlag)){
            request.setAttribute("viewMessage","viewMessage" );
            request.setAttribute("updateAlertSystemLogID",updateAlertSystemLogID);            
            return mapping.findForward("ALERTMESSAGE.VIEW");            
          }else{            
            return mapping.findForward("HOME");
          }
        }
        String redirectURL = loginForm.getUrl();
        if (redirectURL.indexOf("?") > 0) {
          redirectURL += "&isLogin=Y";
        } else {
          redirectURL += "?isLogin=Y";
        }
        response.sendRedirect(redirectURL);
      } catch (Exception ignore) {
        log.error("Cannot redirect url.", ignore);
      }
    }
    
    // Return the mapping to Home by default.
    // for odma return
    
    request.getSession().setAttribute(GlobalConstant.CLIENT_SCREEN_WIDTH_KEY, loginForm.getClientScreenWidth());
    if ("odma".equals(processFlag)){        
      if ((sessionCtn.hasAccessRight(SystemFunctionConstant.DMS_PUBLIC_FOLDER, "R"))
          || (sessionCtn.hasAccessRight(SystemFunctionConstant.DMS_PERSONAL_FOLDER, "R"))){
        request.setAttribute("odmaGetType","login" );
        request.setAttribute("result","success" );
        request.setAttribute("inforCode","MESSAGE_LOGIN_01" );
        return mapping.findForward("DMS.ODMA_RESULT");        
      }else{// if not right access dms, don't allow user login                 
        request.setAttribute("odmaGetType","login" );
        request.setAttribute("result","failed" );
        request.setAttribute("inforCode","ERROR_LOGIN_08" );
        return mapping.findForward("DMS.ODMA_RESULT");
      }
    }else if ("alertMessage".equals(processFlag)){
      request.setAttribute("viewMessage","viewMessage" );
      request.setAttribute("updateAlertSystemLogID",updateAlertSystemLogID);
      return mapping.findForward("ALERTMESSAGE.VIEW");            
    }else{      
      return mapping.findForward("HOME");
    }
  }
  
}
